-- 后端节点的主文件， 会被命名成 .router
-- 这个是运行在node节点上的一个router，处理所有来访问这个节点的请求
-- 后台节点，只有不同节点， 本节点之间的调用
-- 不同节点调用，全部走 .router 来调用， 本节点调用，全部使用一级命令的模式，而且不用process了
local filename = "router.lua"

local skynet = require "skynet"
local cluster = require "skynet.cluster"
local redisdao = require "redisdao"
require "skynet.manager"

local json = require "cjson"
json.encode_sparse_array(true,1,1)
local filelog = require "filelog"
local routerbase = require "routerbase"
local timetool = require "timetool"

require "pubenum"

local Router = routerbase:new()

Router.rankdata = {}
Router.gamenode_config_ab = require "gamenode_config_ab"
Router.clientver = ""
Router.massmail_list = {}

--支付通道列表
Router.paychannel = "{}"

-- 这里添加命令， 简单的命令，可以直接写在本文件
function Router:init()
	self:add_func("popmessage")
end

-- 关键接口：暴露给外部的接口，给rids上的agent发通知消息，
-- 主要是游戏node 来调用，广播，通知玩家
-- 先通过调用主节点的longtcpmng，获得对应的agent，然后调用 agent:notify_client
-- 发送可能比较慢，所以用send调用，然后直接立刻返回 true
-- 参数： rids, msgname, msgbody, retcode, retstr, fromnode
-- 节点可以把包名放在 msgname里面，也可以标明来自哪个node，此处做拼接，目前看起来都是包名直接拼接在msgname中
function Router.CMD.notify(rids, msgname, msgbody, retcode, retstr, fromnode )
	-- 广播的方法 一 平行调用处理，此处循环获得agent，然后分别调用
	-- local agent
	-- if fromnode then
	-- 	if string.sub(fromnode, -4, -1) == "node" then
	-- 		fromnode = string.sub(fromnode, 1, -5)
	-- 	end
	-- 	msgname = fromnode .. "." .. msgname
	-- end

	-- for k,rid in pairs(rids) do
	-- 	agent = skynet.call(".mainnode", "lua", "cmd", "get_agent_by_rid", rid)
	-- 	if agent then
	-- 		skynet.send(agent, "lua", "cmd", "notify_client", msgname, msgbody, retcode, retstr)
	-- 	end
	-- end

	-- 广播的方法 二，串型处理方式， 全部send丢给gatenode处理，router立刻可以去处理其他内容
	-- 相对来说 gatenode 节点比较清闲， notify的优先级相对不是最高，不会占用 router的资源
	-- if fromnode then
	-- 	if string.sub(fromnode, -4, -1) == "node" then
	-- 		fromnode = string.sub(fromnode, 1, -5)
	-- 	end
	-- 	msgname = fromnode .. "." .. msgname
	-- end
	skynet.send(".mainnode", "lua", "cmd", "notify", rids, msgname, msgbody, retcode, retstr )
	return true
end

-- 游戏节点初始化通知gate服
function Router.CMD.gamenode_init(nodename)
	local agents = skynet.call(".mainnode", "lua", "cmd", "get_all_agents")
	if agents then
		for rid, agent in pairs(agents) do
			skynet.send(agent.agent, "lua", "cmd", "gamenode_init", nodename)
		end
	end
	skynet.call(".roletablestate", "lua", "del_gamenode_code", nodename)
end

--  桌子的调用，暂时放到 gatenode上来实现了。
function Router.CMD.create_table_code( ... )
	return skynet.call(".roletablestate", "lua", "create_table_code", ... )
end

-- 自建桌结束的时候，游戏节点要向hallnode发放销毁桌子的消息
function Router.CMD.del_table_code( ... )
	return skynet.call(".roletablestate", "lua", "del_table_code", ... )
end


-- gamenode在玩家进入桌子成功后，调用gate上的这个接口
function Router.CMD.role_enter_table(rid, gamenode, table_index)
	local agent = skynet.call(".mainnode", "lua", "cmd", "get_agent_by_rid", rid)
	if agent then
		return skynet.call(agent, "lua", "cmd", "enter_table", rid, gamenode, table_index)
	else
		return -1 -- 玩家不在线
	end
end

-- gamenode在玩家离开桌子成功后，调用gate上的这个接口,这里需要验证一下玩家的diamonde
function Router.CMD.role_leave_table(rid, gamenode, table_index, ev_diamond)
	local agent = skynet.call(".mainnode", "lua", "cmd", "get_agent_by_rid", rid)
	if agent then
		return skynet.call(agent, "lua", "cmd", "leave_table", rid, gamenode, table_index, ev_diamond)
	else
        if rid and rid >= 100000 and rid <= 9999999 then
            skynet.send(".roletablestate", "lua", "rid_leave_table", rid, gamenode, table_index, true)
        end
		return -1  -- 玩家不在线
	end
end

-- 使用change， set ，分开，主要是想change可以用来做数字货币item的修改，传入改变量
-- 可以用在金币，房卡，经验，比赛场次
-- 为了简化item的值，数据库设计约束，主要字段名唯一，然后处理的时候，根据item，找到对应的表
-- set 用在设置item的最终数量上
-- 修改某个agent的数据，这里也是可以带列表形式的
-- 所有的change，最终给还是变成 set， 因为后端的data（redis， mysql）都是指数据存储，不是数据运算
-- 暂时简化 chanitem 的使用，只处理money类型： coin, diamond, lock_coin, lock_diamond, fangk, 
-- 而且这个chnge item 是同时生效的，只有里面的item都是可以改变的（不会出现负数），才去做真正的改变，
-- 否则一个都不生效

-- comment : 至少包含节点名称， 节点唯一trade_id， 修改原因编码 reason_id, 上层节点comment:upper
-- 			如果是桌子来的，要有 table_uuid
-- {formnode, tradeid, reasonid, upper}
-- 如果是多节点调用 upper 就是上层的的comment结构
-- 这里单独拎出来，只修改 money相关数据库，全部在rs_money 一张表中
-- 暂时只考虑修改coin， fangka 改变钻石的值，至少有下面三个接口
function Router.CMD.change_money(rid, itemvalues, comment)
	local agent = skynet.call(".mainnode", "lua", "cmd", "get_agent_by_rid", rid)
	if agent then
		return skynet.call(agent, "lua", "cmd", "change_money", itemvalues, comment)
	else
		return skynet.call(".offlinerole", "lua", "change_money", rid, itemvalues, comment)
	end
end

--
--减少玩家金钱（钻石，房卡，金豆）
--money_type 货币类型 1房卡 2金豆 3金币
--value 扣除值 ，
--
function Router.CMD.reduce_money(rid, money_type, value)
    value = tonumber(value)
    money_type = tonumber(money_type)
    if value <= 0 or not money_type then
        return false
    end
    value = -value

    local moneys = {[1] = "fangka", [2] = "diamond", [3] = "coin"}
    local name = moneys[money_type]
    if not name then
        return false
    end

    local itemvalues = {}
    itemvalues[name] = value
	local result = Router.CMD.change_money(rid, itemvalues, {})
    if result then
        local logstr = nil
        local endvalue = result[name]
        local beginvalue = result[name] - value
        if name == "fangka" then
            logstr = string.format("%d,%d,%d,%d,%d,%d,%d,%d", EFangKaChange.REDUCEFANGKA, rid, 0, value, 0, 0, beginvalue, endvalue)
            skynet.send(".fangkalog", "lua", "write", logstr)
        elseif name == "diamond" then
            logstr = string.format("%d,%d,%d,%d,%d,%d,%d,%d,%d,%s,%s", EDiamondChange.GM_REDUCE, rid, 0, value, 0, 0, beginvalue, endvalue, 0, nil, nil)
            skynet.send(".diamondlog", "lua", "write", logstr)
        elseif name == "coin" then
            logstr = string.format("%d,%d,%d,%d,%d,%d,%d,%d,%d,%s,%s", ECoinChange.GM_REDUCE, rid, 0, value, 0, 0, beginvalue, endvalue, 0, nil, nil)
            skynet.send(".coinlog", "lua", "write", logstr)
        end
        return true
    end

    return false
end

--
--减少玩家道具
--prop_id 道具id
--value 扣除值
--
function Router.CMD.reduce_prop(rid, prop_id, value)
    value = tonumber(value)
    prop_id = tonumber(prop_id)
    if value <= 0 or not prop_id then
        return false
    end
    value = -value

    local status = nil
    local result = nil

    local agent = skynet.call(".mainnode", "lua", "cmd", "get_agent_by_rid", rid)
	if agent then
		status,result = pcall(skynet.call, agent, "lua", "cmd", "reduce_prop", prop_id, value)
        if not status then
            filelog.sys_error("charge prop failed!",rid, prop_id, value)
            result = skynet.call(".offlinerole", "lua", "reduce_prop", rid, prop_id, value)
        end
	else
		result = skynet.call(".offlinerole", "lua", "reduce_prop", rid, prop_id, value)
	end

    return result
end

-- 充值钻石，其实和change_money 一样的操作
function Router.CMD.charge_diamond(rid, value, money, comment)
    comment = comment or {}
	value = tonumber(value)
	if value <= 0 then
		return false
	end

    local status = false
	local agent = skynet.call(".mainnode", "lua", "cmd", "get_agent_by_rid", rid)

	if agent then
        local is_ok = true
		is_ok,status = pcall(skynet.call, agent, "lua", "cmd", "charge_diamond", value, comment)
        if not is_ok then
            filelog.sys_error("charge diamond failed!",rid,value,money,comment)
            status = skynet.call(".offlinerole", "lua", "charge_diamond", rid, value, comment)
        end
	else
		status = skynet.call(".offlinerole", "lua", "charge_diamond", rid, value, comment)
		agent = skynet.call(".mainnode", "lua", "cmd", "get_agent_by_rid", rid)
		if agent then
			skynet.send(agent, "lua", "cmd", "refresh_money", value)
		end
	end

    --保存充值记录
    if status then
        skynet.send(".roletablestate", "lua", "write_chargerecord", rid, value, money, comment.charge_type)
    end

    return status
end

-- 充值房卡，单独列出来做
function Router.CMD.charge_fangka(rid, value, comment)
	value = tonumber(value)
	if value <= 0 then
		return false
	end

    local status = nil
    local result = nil

	local agent = skynet.call(".mainnode", "lua", "cmd", "get_agent_by_rid", rid)
	if agent then
		status,result = pcall(skynet.call, agent, "lua", "cmd", "charge_fangka", value, comment)
        if not status then
            filelog.sys_error("charge fangka failed!",rid,value,comment)
            result = skynet.call(".offlinerole", "lua", "charge_fangka", rid, value, comment)
        end
	else
		result = skynet.call(".offlinerole", "lua", "charge_fangka", rid, value, comment)
	end

    return result
end

-- 充值道具
function Router.CMD.charge_prop(rid, prop_id, value, comment)
    comment = comment or { }
    rid = tonumber(rid)
	value = tonumber(value)
    prop_id = tonumber(prop_id)
	if value <= 0 or prop_id <= 0 then
		return false
	end

    local status = nil
    local result = nil

	local agent = skynet.call(".mainnode", "lua", "cmd", "get_agent_by_rid", rid)
	if agent then
		status,result = pcall(skynet.call, agent, "lua", "cmd", "charge_prop", prop_id, value, comment)
        if not status then
            filelog.sys_error("charge prop failed!",rid,value,comment)
            result = skynet.call(".offlinerole", "lua", "charge_prop", rid, prop_id, value, comment)
        end
	else
		result = skynet.call(".offlinerole", "lua", "charge_prop", rid, prop_id, value, comment)
	end

    return result
end

-- rid_values是一个结构 {rid->{beginvalue:xxx, value:yyy endvalue:zzz, }}
-- 里面的value 是个正数
function Router.CMD.game_sub_fuwufei(rid_values, comment)
    local nodename = string.match(comment.table_uuid,"(.+)node_")

	-- 参照广播的做法，全部丢给gatenode去处理，本质都是一样的
	skynet.send(".mainnode", "lua", "cmd", "rids_broadcast_func", "game_sub_fuwufei",  rid_values, comment, nodename, 1)
	local sumvalue = 0
	local sumrole = 0
	local tmpridfwf = {}
	for k,v in pairs(rid_values) do
		sumvalue = sumvalue + v.value
		sumrole = sumrole + 1
		tmpridfwf[k] = v.value
	end
	tmpridfwf = json.encode(tmpridfwf)

	-- 桌子uuid，交易号，序列，扣了多少人，总扣了多少钱
    local logstr = nil
    if nodename == "wzq" then
	    logstr = string.format("%d,%s,%s,%s,%s,%d,%d", EGateAction.WZQ_FUWUFEI, comment.table_uuid, comment.start_time, comment.table_tradeid, tmpridfwf, sumrole, sumvalue)
    elseif nodename == "xq" then
	    logstr = string.format("%d,%s,%s,%s,%s,%d,%d", EGateAction.XQ_FUWUFEI, comment.table_uuid, comment.start_time, comment.table_tradeid, tmpridfwf, sumrole, sumvalue)
    else
        logstr = string.format("%d,%s,%s,%s,%s,%d,%d", EGateAction.FUWUFEI, comment.table_uuid, comment.start_time, comment.table_tradeid, tmpridfwf, sumrole, sumvalue)
    end
	skynet.send(".gamedatalog", "lua", "write", logstr)

	return true
end

-- rid_values是一个结构 {rid->{beginvalue:xxx, value:yyy endvalue:zzz, }}
-- 里面的value 是个正数
-- 扣房费
function Router.CMD.game_sub_fangfei(rid_values, comment)
	comment = comment or {}
	comment.is_fangfei = true
	return Router.CMD.game_sub_diamond(rid_values, comment)
end

-- rid_values是一个结构 {rid->{beginvalue:xxx, value:yyy endvalue:zzz, }}
-- 里面的value 是个正数
function Router.CMD.game_sub_diamond(rid_values, comment)
    local nodename = string.match(comment.table_uuid,"(.+)node_")
	
	-- 参照广播的做法，全部丢给gatenode去处理，本质都是一样的
	skynet.send(".mainnode", "lua", "cmd", "rids_broadcast_func", "game_sub_diamond",  rid_values, comment, nodename)
	local sumvalue = 0
	local sumrole = 0
	local tmpridfwf = {}
	for k,v in pairs(rid_values) do
		sumvalue = sumvalue + v.value
		sumrole = sumrole + 1
		tmpridfwf[k] = v.value
	end
	tmpridfwf = json.encode(tmpridfwf)

    -- 桌子uuid，交易号，序列，扣了多少人，总扣了多少钱
    local logstr = nil
    if nodename == "wzq" then
	    logstr = string.format("%d,%s,%s,%s,%s,%d,%d", EGateAction.WZQ_FUWUFEI, comment.table_uuid, comment.start_time, comment.table_tradeid, tmpridfwf, sumrole, sumvalue)
    elseif nodename == "xq" then
	    logstr = string.format("%d,%s,%s,%s,%s,%d,%d", EGateAction.XQ_FUWUFEI, comment.table_uuid, comment.start_time, comment.table_tradeid, tmpridfwf, sumrole, sumvalue)
    else
        logstr = string.format("%d,%s,%s,%s,%s,%d,%d", EGateAction.FUWUFEI, comment.table_uuid, comment.start_time, comment.table_tradeid, tmpridfwf, sumrole, sumvalue)
    end
	skynet.send(".gamedatalog", "lua", "write", logstr)

	return true
end
-- rid_values是一个结构 {rid->{beginvalue:xxx, value:yyy endvalue:zzz, }}
-- 里面的value 是个正数
function Router.CMD.game_sub_coin(rid_values, comment)
    local nodename = string.match(comment.table_uuid,"(.+)node_")

	-- 参照广播的做法，全部丢给gatenode去处理，本质都是一样的
	skynet.send(".mainnode", "lua", "cmd", "rids_broadcast_func", "game_sub_coin",  rid_values, comment, nodename)
	local sumvalue = 0
	local sumrole = 0
	local tmpridfwf = {}
	for k,v in pairs(rid_values) do
		sumvalue = sumvalue + v.value
		sumrole = sumrole + 1
		tmpridfwf[k] = v.value
	end
	tmpridfwf = json.encode(tmpridfwf)

	-- 桌子uuid，交易号，序列，扣了多少人，总扣了多少钱
    local logstr = nil
    if nodename == "wzq" then
	    logstr = string.format("%d,%s,%s,%s,%s,%d,%d", EGateAction.WZQ_FUWUFEI, comment.table_uuid, comment.start_time, comment.table_tradeid, tmpridfwf, sumrole, sumvalue)
    elseif nodename == "xq" then
	    logstr = string.format("%d,%s,%s,%s,%s,%d,%d", EGateAction.XQ_FUWUFEI, comment.table_uuid, comment.start_time, comment.table_tradeid, tmpridfwf, sumrole, sumvalue)
    else
	    logstr = string.format("%d,%s,%s,%s,%s,%d,%d", EGateAction.COIN_FUWUFEI, comment.table_uuid, comment.start_time, comment.table_tradeid, tmpridfwf, sumrole, sumvalue)
    end
	skynet.send(".gamedatalog", "lua", "write", logstr)

	return true
end

-- 金豆场的单局结算，同时做了战绩
-- 里面所有的sum(value) == 0
-- coin的rid_values里增加一个othervalue字段，表示扣除的钻石数
function Router.CMD.game_balance_coin_diamond(rid_values_list, comment)
    local status = nil
    local result = true

    --设置othervalue的值
    for rid,item in pairs(rid_values_list.coin) do
        if rid_values_list.diamond then
            local othervalues = rid_values_list.diamond[rid] or { }
            item.othervalue = othervalues.value
        end
    end
    
    for moneyname,rid_values in pairs(rid_values_list) do
        if moneyname == "diamond" then
            status = Router.CMD.game_balance_diamond(rid_values,comment, true)
        elseif moneyname == "coin" then
            status = Router.CMD.game_balance_coin(rid_values,comment)
        else
            filelog.sys_error("error money type!",moneyname,rid_values,comment)
        end
        if not status then
            result = false
        end
    end

    return result
end

-- 金豆场的单局结算，同时做了战绩
-- 里面所有的sum(value) == 0
function Router.CMD.game_balance_coin(rid_values, comment)
    local nodename = string.match(comment.table_uuid,"(.+)node_")

	local sumzero = 0
	local sumvalue = 0
	local sumrole = 0
	local tmpridfwf = {}
	for k,v in pairs(rid_values) do
		sumzero = sumzero + (v.real_change or 0)
		sumvalue = sumvalue + math.abs(v.value)
		sumrole = sumrole + 1
		tmpridfwf[k] = v.value
	end
	tmpridfwf = json.encode(tmpridfwf)

	if sumzero ~= 0 then 
		-- 记录错误日志
		filelog.sys_error("game_balance_coin error",rid_values,comment)
		return false
	end
    
	skynet.send(".mainnode", "lua", "cmd", "rids_broadcast_func", "game_balance_coin",  rid_values, comment, nodename)

	-- 桌子uuid，交易号，序列，多少人参加了结算，变化的绝对值和
    local logstr = ""
    if nodename == "wzq" then
        logstr = string.format("%d,%s,%s,%s,%s,%d,%d", EGateAction.WUZIQI, comment.table_uuid, comment.start_time, comment.table_tradeid, tmpridfwf, sumrole, sumvalue)
    elseif nodename == "xq" then
        logstr = string.format("%d,%s,%s,%s,%s,%d,%d", EGateAction.XIANGQI, comment.table_uuid, comment.start_time, comment.table_tradeid, tmpridfwf, sumrole, sumvalue)
    else
        logstr = string.format("%d,%s,%s,%s,%s,%d,%d", EGateAction.COIN_JIESUAN, comment.table_uuid, comment.start_time, comment.table_tradeid, tmpridfwf, sumrole, sumvalue)
    end
	skynet.send(".gamedatalog", "lua", "write", logstr)

	return true
end

-- 金豆场，中途弃牌，也算失败，要马上扣费，主要用在焖鸡上
function Router.CMD.game_half_coin_diamond(rid_values_list, comment)
    local status = nil
    local result = true

    for moneyname,rid_values in pairs(rid_values_list) do
        if moneyname == "diamond" then
            status = Router.CMD.game_half_diamond(rid_values,comment)
        elseif moneyname == "coin" then
            status = Router.CMD.game_half_coin(rid_values,comment)
        else
            filelog.sys_error("error money type!",moneyname,rid_values,comment)
        end
        if not status then
            result = false
        end
    end

	return result
end

-- 金豆场，中途弃牌，也算失败，要马上扣费，主要用在焖鸡上
function Router.CMD.game_half_coin(rid_values, comment)
	skynet.send(".mainnode", "lua", "cmd", "rids_broadcast_func", "game_half_coin",  rid_values, comment)
	return true
end

-- 钻石场的单局结算，同时做了战绩
-- 里面所有的sum(value) == 0
function Router.CMD.game_balance_diamond(rid_values, comment, is_cointable)
    local nodename = string.match(comment.table_uuid,"(.+)node_")

	local sumzero = 0
	local sumvalue = 0
	local sumrole = 0
	local tmpridfwf = {}
	for k,v in pairs(rid_values) do
	    sumzero = sumzero + (v.real_change or 0)
		sumvalue = sumvalue + math.abs(v.value)
		sumrole = sumrole + 1
		tmpridfwf[k] = v.value
	end
	tmpridfwf = json.encode(tmpridfwf)

	if sumzero ~= 0 then 
		-- 记录错误日志
		filelog.sys_error("game_balance_diamond error",rid_values,comment)
		return false
	end
	skynet.send(".mainnode", "lua", "cmd", "rids_broadcast_func", "game_balance_diamond",  rid_values, comment, nodename, is_cointable)

	-- 桌子uuid，交易号，序列，多少人参加了结算，变化的绝对值和
	local logstr = nil
	if nodename == "wzq" then 
		logstr = string.format("%d,%s,%s,%s,%s,%d,%d", EGateAction.WUZIQI, comment.table_uuid, comment.start_time, comment.table_tradeid, tmpridfwf, sumrole, sumvalue)
	elseif nodename == "xq" then 
		logstr = string.format("%d,%s,%s,%s,%s,%d,%d", EGateAction.XIANGQI, comment.table_uuid, comment.start_time, comment.table_tradeid, tmpridfwf, sumrole, sumvalue)
	else
		logstr = string.format("%d,%s,%s,%s,%s,%d,%d", EGateAction.JIESUAN, comment.table_uuid, comment.start_time, comment.table_tradeid, tmpridfwf, sumrole, sumvalue)
	end
	skynet.send(".gamedatalog", "lua", "write", logstr)
	return true
end

-- 百人游戏钻石场的单局结算
function Router.CMD.brgame_balance_diamond(rid_values, comment)
    local nodename = string.match(comment.table_uuid,"(.+)node_")
	
	local sumvalue = 0
	local sumrole = 0
	local rid_changes = {}
	for k,v in pairs(rid_values) do
		sumvalue = sumvalue + v.value
		sumrole = sumrole + 1
		if v.real_change and tonumber(v.real_change) ~= tonumber(0) then
			rid_changes[k] = v.real_change
		end
	end
	
	--发送玩家输赢
	if next(rid_changes) ~= nil then
		local change_cmd = {
			msghead = { msgname = "game_change" },
		 	msgbody = {
				change_list = rid_changes,
				cur_time = timetool.get_time(),
				game_name = nodename,
				table_tradeid = comment.table_tradeid,
			}
		}
		redisdao.query_data(".gmmqredis", "rpush", "outchangemq", json.encode(change_cmd))
	end
	
	skynet.send(".mainnode", "lua", "cmd", "rids_broadcast_func", "game_balance_diamond",  rid_values, comment, nodename, true)

	-- 桌子uuid，交易号，序列，多少人参加了结算，总结算金额
	local logstr = nil
	if nodename == "wzq" then 
		logstr = string.format("%d,%s,%s,%s,%d,%d", EGateAction.WUZIQI, comment.table_uuid, comment.start_time, comment.table_tradeid, sumrole, sumvalue)
	elseif nodename == "xq" then 
		logstr = string.format("%d,%s,%s,%s,%d,%d", EGateAction.XIANGQI, comment.table_uuid, comment.start_time, comment.table_tradeid, sumrole, sumvalue)
	else
		logstr = string.format("%d,%s,%s,%s,%d,%d", EGateAction.JIESUAN, comment.table_uuid, comment.start_time, comment.table_tradeid, sumrole, sumvalue)
	end
	skynet.send(".gamedatalog", "lua", "write", logstr)
	return true
end

-- 钻石场，中途弃牌，也算失败，要马上扣费，主要用在焖鸡上
function Router.CMD.game_half_diamond(rid_values, comment)
	skynet.send(".mainnode", "lua", "cmd", "rids_broadcast_func", "game_half_diamond",  rid_values, comment)
	return true
end

-- 五子棋结算，实质和 game_balance_diamond,一样，只是入口不同而已。
-- 这里把五子棋转账和普通的结算入口分开，是为了以后在这块做更多的处理
function Router.CMD.wzq_balance_diamond(rid_values, comment, is_cointable)
    local _,table_code = string.match(comment.table_uuid,"(%a+)_(%d+)")

    --检测金豆是否够
    local diamond_ridvalues = rid_values
    if is_cointable then
        diamond_ridvalues = rid_values.diamond or { }
    end

    for rid,item in pairs(diamond_ridvalues) do
        local value = item.value
        if value then
            local agent = skynet.call(".mainnode", "lua", "cmd", "get_agent_by_rid", rid)
            if agent then
                local realdiamond = skynet.call(agent, "lua", "cmd", "get_diamond")
                if realdiamond + value < 0 then
                    return false
                end
            else
                return false
            end
        end
    end

	local status = nil
    if is_cointable then
        status = Router.CMD.game_balance_coin_diamond(rid_values, comment)
    else
        status = Router.CMD.game_balance_diamond(rid_values, comment)
    end

	return status
end

-- 扣房卡参数结构和扣 服务费一致。
function Router.CMD.game_sub_fangka(rid_values, comment)
	local sumvalue = 0
	local sumrole = 0
	local tmpridfwf = {}
	for k,v in pairs(rid_values) do
		sumvalue = sumvalue + math.abs(v.value)
		sumrole = sumrole + 1
		tmpridfwf[k] = v.value
	end
	tmpridfwf = json.encode(tmpridfwf)
	skynet.send(".mainnode", "lua", "cmd", "rids_broadcast_func", "game_sub_fangka",  rid_values, comment)
	-- 桌子uuid，交易号，序列，扣了多少人，总扣了多少房卡
	local logstr = string.format("%d,%s,%s,%s,%s,%d,%d", EGateAction.SUBFANGKA, comment.table_uuid, comment.start_time, comment.table_tradeid, tmpridfwf, sumrole, sumvalue)
	skynet.send(".gamedatalog", "lua", "write", logstr)
	return true
end

-- 房卡场的战绩，最后大结算完成时调用了，采用了钻石计算的格式
function Router.CMD.game_balance_fangka(rid_values, comment)
	local sumzero = 0
	for k,v in pairs(rid_values) do
		sumzero = sumzero + v.value
	end
	if sumzero ~= 0 then 
		-- 记录日志
        filelog.sys_error("game_balance_fangka error",rid_values,comment)
		return false
	end
	skynet.send(".mainnode", "lua", "cmd", "rids_broadcast_func", "game_balance_fangka",  rid_values, comment)
	return true
end

-- 加入跑马灯内容
function Router.CMD.addhrlmsg(msg)
	skynet.send(".horseracelamp", "lua", "addhrlmsg", msg)
end

-- 获得所有跑马灯
function Router.CMD.getallhrlmsg()
	return skynet.call(".horseracelamp", "lua", "getallhrlmsg")
end

-- 删除某条跑马灯
function Router.CMD.delhrlmsg(index, hrltype)
	skynet.send(".horseracelamp", "lua", "delhrlmsg", index, hrltype)
end

-- 修改用户信息,已经要分在线，不在线两种情况
function Router.CMD.updateroleinfo(rid, itemvalues, comment)
	local agent = skynet.call(".mainnode", "lua", "cmd", "get_agent_by_rid", rid)
	if agent then
		return skynet.call(agent, "lua", "cmd", "updateroleinfo", itemvalues, comment)
	else
		return skynet.call(".offlinerole", "lua", "updateroleinfo", rid, itemvalues, comment)
	end
end

-- gm发来的踢人指令
function Router.CMD.kickrole(rid)
	local agent = skynet.call(".mainnode", "lua", "cmd", "get_agent_by_rid", rid)
	if agent then
		return skynet.call(agent, "lua", "cmd", "kickoff")
	end
	return false
end

-- gatenode 每次启动，去gm拿一次rankdata
function Router.CMD.get_rank()
	local status, tmpdata = skynet.pcall(cluster.call, "gmnode", ".router", "get_rank")
	if status and type(tmpdata) == "table" then
		Router.rankdata = tmpdata
        skynet.error("-->Get rank from gmnode ok!")
	else
        skynet.error("-->Get rank from gmnode falied!")
        return false
    end
end

-- gm更新了rank，然后push到这里
function Router.CMD.setrank(rankdata)
	Router.rankdata = rankdata
end

-- 本节点的 agent来调用，其实算是内部接口
function Router.CMD.getrank(ranktype)
	return Router.rankdata[ranktype]
end

-- gatenode 每次启动，去gm拿一次massmail_list
function Router.CMD.get_massmail()
	local status, tmpdata = skynet.pcall(cluster.call, "gmnode", ".router", "get_massmail")
	if status and type(tmpdata) == "table" and tmpdata.retcode == nil then
		Router.massmail_list = tmpdata
        skynet.error("-->Get massmail from gmnode ok!")
	else
        skynet.error("-->Get massmail from gmnode falied!")
    end
end

-- gm更新了massmail_list，然后push到这里
function Router.CMD.setmassmail(massmail_list)
	Router.massmail_list = massmail_list
end

-- 本节点的 agent来调用，其实算是内部接口
function Router.CMD.getmassmail()
	return Router.massmail_list
end

--发送群发邮件
function Router.CMD.send_massmail(msgbody)
    local onlinerids = skynet.call(".roletablestate", "lua", "get_onlinerids")
    for rid,_ in pairs(onlinerids) do
        local agent = skynet.call(".mainnode", "lua", "cmd", "get_agent_by_rid", rid)
	    if agent then
		    skynet.send(agent, "lua", "cmd", "send_massmail", msgbody.keyid, msgbody.fields)
	    end
    end
end

-- gm更新了gamenode_config，然后push到这里
-- ab， 就是ab服的意思， 要么是a， 要么是b
function Router.CMD.set_gamenode_config_ab(game, ab)
	Router.gamenode_config_ab[game] = ab
	-- 要把所有agent里面的这个配置去修改，这样agent就知道去新的游戏服开始游戏了
	local agents = skynet.call(".mainnode", "lua", "cmd", "get_all_agents")
	if agents then
		for rid, agent in pairs(agents) do
			skynet.send(agent.agent, "lua", "cmd", "set_gamenode_config_ab", game, ab)
		end
	end
end

-- 本节点的 agent来调用，其实算是内部接口
function Router.CMD.get_gamenode_config_ab()
	return Router.gamenode_config_ab
end

function Router.CMD.set_system_ad(addata)
	skynet.send(".hallad", "lua", "set_system_ad", addata)
end

--  获取用户在线统计
function Router.CMD.get_online_state( ... )
	return skynet.call(".roletablestate", "lua", "get_online_state", ... )
end

-- 发新邮件，gmnode来调用
function Router.CMD.newmail(...)
	return skynet.call(".mailbox", "lua", "newmail", ...)
end

-- 删除桌子
function Router.CMD.destroytable(table_code)
	local info = skynet.call(".roletablestate", "lua", "gettablebycode", table_code )
    cluster.send(info.realnode, ".router", "destroytable", table_code, info.table_index)
end

-- 获得桌子所有玩家rid
function Router.CMD.get_table_allrid(table_code)
	local info = skynet.call(".roletablestate", "lua", "gettablebycode", table_code )
    local rids = skynet.call(".roletablestate", "lua", "get_table_allrid", info.realnode,info.table_index)
    return rids or {}
end

-- 检测玩家是否已在桌子内
function Router.CMD.check_role_state(rid, enter_diamond, is_cointable)
	local agent = skynet.call(".mainnode", "lua", "cmd", "get_agent_by_rid", rid)
	if agent then
		return skynet.call(agent, "lua", "cmd", "check_role_state",enter_diamond, is_cointable)
	else
		return true   --离线
	end
end

-- 通知所有在线玩家
function Router.CMD.notify_all_online_roles(msg)
	local onlinerids = skynet.call(".roletablestate", "lua","get_onlinerids")
    local rids = {}
    for rid,_ in pairs(onlinerids) do
        table.insert(rids,rid)
    end
    Router.CMD.notify(rids,"messagetipsN",{tips = msg})
end

-- 玩家开始匹配
function Router.CMD.role_start_match(rid, gamenode, tabletype)
	local agent = skynet.call(".mainnode", "lua", "cmd", "get_agent_by_rid", rid)
	if agent then
		return skynet.call(agent, "lua", "cmd", "start_match", rid, gamenode, tabletype)
	else
		return -1  -- 玩家不在线
	end
end

-- 玩家结束匹配
function Router.CMD.role_end_match(rid, gamenode, tabletype)
	local agent = skynet.call(".mainnode", "lua", "cmd", "get_agent_by_rid", rid)
	if agent then
		return skynet.call(agent, "lua", "cmd", "end_match", rid, gamenode, tabletype)
	else
        skynet.send(".roletablestate", "lua", "rid_end_match", rid, gamenode, tabletype)
		return -1  -- 玩家不在线
	end
end

-- gatenode 每次启动，去gm获得clientver
function Router.CMD.get_clientver()
    local result, result_data = redisdao.query_data(".gmmqredis", "get", "clientver")
	if result_data then
		Router.clientver = result_data
    end
    skynet.error("-->Get clientver from gmnode OK",Router.clientver)
end

-- gm更新了clientver，然后push到这里
function Router.CMD.setclientver(clientver)
    filelog.error("---new clientver",clientver)
	Router.clientver = clientver
end

-- 本节点调用，其实算是内部接口
function Router.CMD.getclientver()
	return Router.clientver
end

-- 获得玩家所在桌子信息{table_index, nodename, table_time}
function Router.CMD.get_rid_tableinfo(rid)
	return skynet.call(".roletablestate", "lua","get_rid_tableinfo", rid)
end

--
--封锁玩家账号
--
function Router.CMD.blocked_rid(rid)
   local result = skynet.call(".roletablestate", "lua","blocked_rid", rid)
   Router.CMD.kickrole(rid)

   return result
end

--
--解封玩家
--
function Router.CMD.unblocked_rid(rid)
    return skynet.call(".roletablestate", "lua","unblocked_rid", rid)
end

--
--检测玩家是否被封号
--
function Router.CMD.check_rid_isblocked(rid)
   return skynet.call(".roletablestate", "lua","check_rid_isblocked", rid)
end

--
--更新白名单,重新去redis读取
--
function Router.CMD.update_whitelist()
    skynet.send(".roletablestate", "lua","update_whitelist")
end

--
--更改白名单状态：关闭或打开白名单
--
function Router.CMD.change_whitelist_state(newstate)
    skynet.send(".roletablestate", "lua","change_whitelist_state", newstate)
end

--
--检测玩家是否是否在白名单
--
function Router.CMD.check_rid_iswhitelist(rid)
   return skynet.call(".roletablestate", "lua","check_rid_iswhitelist", rid)
end

--
--设置游戏服结束标记
--nodename 节点名，形如：mjzznode psznode dnnode phznode pdknode wzqnode
--
function Router.CMD.set_gameend_flag(nodename)
    if not nodename then return false end
    skynet.pcall(cluster.send, nodename, ".router", "set_gameend_flag")
end

--
--设置桌子结束标记
--table_code桌号
--
function Router.CMD.set_tableend_flag(table_code)
    if not table_code or table_code < 1 then
        return 
    end

    local info = skynet.call(".roletablestate", "lua", "gettablebycode", table_code)
    if info then
        cluster.send(info.realnode, ".router", "set_tableend_flag", table_code)
    end
end

--
--设置静态跑马灯配置
--
function Router.CMD.sethrlconfigmsg(configmsg)
    return skynet.call(".horseracelamp", "lua", "sethrlconfigmsg", configmsg)
end

--
--清空玩家桌子信息
--
function Router.CMD.clear_role_tableinfo(rid)
    local nodeab = Router.gamenode_config_ab

	---清除玩家游戏中桌子信息
	local nodes = {"dn", "psz", "ernn", "brnn", "ttz", "rb", "lhd", "fish", "hbsl", "ddz", "bjl", "bm", "fqzs", "sgj",}
	for k, v in pairs(nodes) do
        local nodename = v .. "nod" .. ( nodeab[v] or "e" )
		skynet.pcall(cluster.send, nodename, ".router", "clear_player_state", rid)
	end
    local agent = skynet.call(".mainnode", "lua", "cmd", "get_agent_by_rid", rid)
	if agent then
		return skynet.call(agent, "lua", "cmd", "clear_tableinfo", rid)
	else
        redisdao.query_data(".gmmqredis", "del", rid .. ":intotable")
		return -1  -- 玩家不在线
	end
end

--
--获得匹配队列等待玩家列表
--
function Router.CMD.get_wait_rolelist(nodename)
    local realname = nodename .. "nod" .. ( Router.gamenode_config_ab[nodename] or "e" )
    local status,result = skynet.pcall(cluster.call, realname, ".router", "get_wait_rolelist")

    return result
end

--
--重置匹配队列
--
function Router.CMD.reset_matchqueue(nodename)
    local realname = nodename .. "nod" .. ( Router.gamenode_config_ab[nodename] or "e" )
    local status,result = skynet.pcall(cluster.call, realname, ".router", "reset_matchqueue")

    return result
end

-- gatenode 每次启动，从reids读取paychannel
function Router.CMD.get_paychannel()
    local result, result_data = redisdao.query_data(".gmmqredis", "get", "allpaychannel")
	if result and type(result_data) == "string" then
		Router.paychannel = result_data
    end
    skynet.error("-->Get paychannel from redis OK")
end

--
--设置支付通道
--
function Router.CMD.setpaychannel(paychannel)
    if type(paychannel) == "string" then
        Router.paychannel = paychannel
    end
end

--
--获得支付通道
--
function Router.CMD.getpaychannel()
   return {paychannel = Router.paychannel}
end

--
--模拟客户端发送消息
--
function Router.CMD.simulate_client(rid, ...)
    local agent = skynet.call(".mainnode", "lua", "cmd", "get_agent_by_rid", rid)
	if agent then
		skynet.send(agent, "lua", "simulate_client", ...)
	else
        --todo
    end
end

function Router.CMD.get_roleinfo_by_rid(rid)
	-- body
	local agent = skynet.call(".mainnode", "lua", "cmd", "get_agent_by_rid", rid)
	if agent then
		local roleinfo = skynet.call(agent, "lua", "cmd", "myroleinfo")
		if roleinfo then
			return roleinfo
		end
	else
		return {}
	end
end

--
--更新游戏权值表
--gamename 游戏名，形如：lhj,sgj,dn
--
function Router.CMD.update_weight_list(gamename, new_w_list)
    local nodeab = Router.gamenode_config_ab
    local nodename = gamename .. "nod" .. ( nodeab[gamename] or "e" )
    skynet.pcall(cluster.send, nodename, ".router", "update_weight_list", new_w_list)
end

--
--设置游戏输钱上限
--gamename 游戏名，形如：lhd,rb,brnn
--
function Router.CMD.set_system_lose_limit(gamename, loselimit_base, loselimit_factor)
    local nodeab = Router.gamenode_config_ab
    local nodename = gamename .. "nod" .. ( nodeab[gamename] or "e" )
    skynet.pcall(cluster.send, nodename, ".router", "set_system_lose_limit", loselimit_base, loselimit_factor)
end

--
--设置游戏机器人数量
--gamename 游戏名，形如：lhd,rb,brnn
--base_num 机器人基础数量
--inc_factor 机器人增加系数
--min_num 机器人最小数量,可为nil
--
function Router.CMD.set_game_robot_num(gamename, base_num, inc_factor, min_num)
    local nodeab = Router.gamenode_config_ab
    local nodename = gamename .. "nod" .. ( nodeab[gamename] or "e" )
    skynet.pcall(cluster.send, nodename, ".router", "set_game_robot_num", base_num, inc_factor, min_num)
end

--
--获得游戏服机器人运行状态
--
function Router.CMD.get_game_robot_state(gamename)
    local nodeab = Router.gamenode_config_ab
    local nodename = gamename .. "nod" .. ( nodeab[gamename] or "e" )
    local status,result = skynet.pcall(cluster.call, nodename, ".router", "get_game_robot_state")
    return result
end

--
--获得游戏服机器人数量
--
function Router.CMD.get_game_robot_num(gamename)
    local nodeab = Router.gamenode_config_ab
    local nodename = gamename .. "nod" .. ( nodeab[gamename] or "e" )
    local status,result = skynet.pcall(cluster.call, nodename, ".router", "get_game_robot_num")
    return result
end

--
--设置游戏服机器人状态
--gamename 游戏名，形如sgj bm fqzs
--state:true运行机器人 false关闭机器人
--
function Router.CMD.set_game_robot_state(gamename, state)
    local nodeab = Router.gamenode_config_ab
    local nodename = gamename .. "nod" .. ( nodeab[gamename] or "e" )
    skynet.pcall(cluster.send, nodename, ".router", "set_game_robot_state", state)
end

--
--检测是否触发任务
--
function Router.CMD.check_is_trigger_task(...)
    skynet.send(".tasksystem", "lua", "check_is_trigger_task", ...)
end

--奖池抽水
function Router.CMD.jackpot_sub_coin(rid_values, comment)
    local nodename = string.match(comment.table_uuid,"(.+)node_")

	-- 参照广播的做法，全部丢给gatenode去处理，本质都是一样的
	skynet.send(".mainnode", "lua", "cmd", "rids_broadcast_func", "jackpot_sub_coin",  rid_values, comment, nodename)
	local sumvalue = 0
	local sumrole = 0
	local tmpridfwf = {}
	for k,v in pairs(rid_values) do
		sumvalue = sumvalue + v.value
		sumrole = sumrole + 1
		tmpridfwf[k] = v.value
	end
	tmpridfwf = json.encode(tmpridfwf)

	-- 桌子uuid，交易号，序列，扣了多少人，总扣了多少钱
    local logstr = string.format("%d,%s,%s,%s,%s,%d,%d", EGateAction.COIN_ADD_JACKPOT, comment.table_uuid, comment.start_time, comment.table_tradeid, tmpridfwf, sumrole, sumvalue)
	skynet.send(".gamedatalog", "lua", "write", logstr)

	return true
end

--奖池抽水
function Router.CMD.jackpot_sub_diamond(rid_values, comment)
    local nodename = string.match(comment.table_uuid,"(.+)node_")

	-- 参照广播的做法，全部丢给gatenode去处理，本质都是一样的
	skynet.send(".mainnode", "lua", "cmd", "rids_broadcast_func", "jackpot_sub_diamond",  rid_values, comment, nodename)
	local sumvalue = 0
	local sumrole = 0
	local tmpridfwf = {}
	for k,v in pairs(rid_values) do
		sumvalue = sumvalue + v.value
		sumrole = sumrole + 1
		tmpridfwf[k] = v.value
	end
	tmpridfwf = json.encode(tmpridfwf)

	-- 桌子uuid，交易号，序列，扣了多少人，总扣了多少钱
    local logstr = string.format("%d,%s,%s,%s,%s,%d,%d", EGateAction.ADD_JACKPOT, comment.table_uuid, comment.start_time, comment.table_tradeid, tmpridfwf, sumrole, sumvalue)
	skynet.send(".gamedatalog", "lua", "write", logstr)

	return true
end

--开奖
--gamename 游戏名，形如dn
function Router.CMD.open_jackpot_coin(gamename, rid_values, comment)
    skynet.send(".mainnode", "lua", "cmd", "rids_broadcast_func", "open_jackpot_coin",  rid_values, comment)
    --skynet.send(".roletablestate", "lua", "update_system_jackpot", gamename, value, comment)

    local sumvalue = 0
	local sumrole = 0
	local tmpridfwf = {}
	for k,v in pairs(rid_values) do
		sumvalue = sumvalue + v.value
		sumrole = sumrole + 1
		tmpridfwf[k] = v.value
	end
	tmpridfwf = json.encode(tmpridfwf)

	-- 桌子uuid，交易号，序列，扣了多少人，总扣了多少钱
    local logstr = string.format("%d,%s,%s,%s,%s,%d,%d", EGateAction.COIN_SUB_JACKPOT, comment.table_uuid, comment.start_time, comment.table_tradeid, tmpridfwf, sumrole, sumvalue)
	skynet.send(".gamedatalog", "lua", "write", logstr)

    return true
end

--开奖
--gamename 游戏名，形如dn
function Router.CMD.open_jackpot_diamond(gamename, rid_values, comment)
    skynet.send(".mainnode", "lua", "cmd", "rids_broadcast_func", "open_jackpot_diamond",  rid_values, comment)
    --skynet.send(".roletablestate", "lua", "update_system_jackpot", gamename, value, comment)

    local sumvalue = 0
	local sumrole = 0
	local tmpridfwf = {}
	for k,v in pairs(rid_values) do
		sumvalue = sumvalue + v.value
		sumrole = sumrole + 1
		tmpridfwf[k] = v.value
	end
	tmpridfwf = json.encode(tmpridfwf)

	-- 桌子uuid，交易号，序列，扣了多少人，总扣了多少钱
    local logstr = string.format("%d,%s,%s,%s,%s,%d,%d", EGateAction.SUB_JACKPOT, comment.table_uuid, comment.start_time, comment.table_tradeid, tmpridfwf, sumrole, sumvalue)
	skynet.send(".gamedatalog", "lua", "write", logstr)

    return true
end

--退出游戏，立即杀掉agent
function Router.CMD.quitgame(rid, ...)
    local agent = skynet.call(".mainnode", "lua", "cmd", "get_agent_by_rid", rid or 0)
    if agent then
	    skynet.send(agent, "lua", "cmd", "close", 1)
    end
end

---检查玩家是否在匹配中
function Router.CMD.check_role_inmatch(rid)
	-- body
	local agent = skynet.call(".mainnode", "lua", "cmd", "get_agent_by_rid", rid)
	if agent then
		return skynet.call(agent, "lua", "cmd", "check_role_inmatch", rid)
	else
		return false
	end
end

--
--更新提现状态
--
function Router.CMD.update_withdraw_state(rid, ...)
    rid = tonumber(rid) or 0
    local agent = skynet.call(".mainnode", "lua", "cmd", "get_agent_by_rid", rid)
    if agent then
	    return skynet.call(agent, "lua", "cmd", "update_withdraw_state", ...)
    else
        return skynet.call(".offlinerole", "lua", "update_withdraw_state", rid, ...)
    end
end

--
--机器人桌内聊天
--gamename 游戏名 形如lhd rb ttz brnn
--table_index 桌子索引
--talkrid 发送聊天消息玩家rid
--msgbody 消息内容 {objrid,chattype,content} 
--@param objrid 发向的玩家rid 
--@param chattype 消息类型5（互动表情） 
--@param content 消息内容,content={content,sex} ,content互动表情id，sex玩家性别
--
function Router.CMD.robot_tablechat(gamename, table_index, talkrid, msgbody)
    local nodeab = Router.gamenode_config_ab
    local ridlist = msgbody.ridlist or {}
    if not gamename or not table_index or not msgbody or not msgbody.content then
        return false
    end

    if type(msgbody.content) ~= "string" then
        msgbody.content = json.encode(msgbody.content) 
    end

    --聊天内容
    local chatmsg = {
	    objrid		= msgbody.objrid or 0,
	    chattype	= msgbody.chattype or 0,
	    content		= msgbody.content or "",
	    talkrid		= talkrid or 0,
    }

    -- 获取玩家列表
    if (not ridlist or #(ridlist) == 0) and gamename then 
        local nodename = gamename .. "nod" .. ( nodeab[gamename] or "e" )
        ridlist = skynet.call(".roletablestate", "lua", "get_table_allrid", nodename, table_index)
    end

    --通知客户端
	local agent = nil
	for _,rid in pairs(ridlist) do
		agent = skynet.call(".mainnode", "lua", "cmd", "get_agent_by_rid", rid)
		if agent then
			skynet.send(agent, "lua", "cmd", "tablechatnotify", chatmsg)
		end
	end

    return true
end

--
--删除邮件
--
function Router.CMD.del_mail(rid, keyid)
    if not rid or not keyid then
        return false
    end

    local now = timetool.get_time()
    skynet.pcall(cluster.call, "datanode", ".router", "delete_rk", rid, "rm_mail", keyid)
	skynet.pcall(cluster.call, "datanode", ".router", "update_rk", rid, "rs_readmail", 0, {last_sendtime = now})
	local agent = skynet.call(".mainnode", "lua", "cmd", "get_agent_by_rid", rid)
	if agent then
		skynet.send(agent, "lua", "cmd", "notify_client", "newmailN", {sendtime = now})
	end

    return true
end

--
--赠送（由后台发来,包括：VIP充值，GM补单，GM奖励等）
--
function Router.CMD.givemoney(...)
	return skynet.call(".givesystem", "lua", "newgiving", ...) 
end

--
--撤销赠送（由后台发来,包括：VIP充值，GM补单，GM奖励等）
--
function Router.CMD.cancelgivemoney(keyid, remark, undorid)
	local newstate = EGiveMoneySate.EGIVEMONEY_STATE_HAD_UNDO
	skynet.send(".givesystem", "lua", "update_givemoney_state", keyid, newstate, remark, undorid) 
end

skynet.start(function()
	Router:start()
end)
